/**
* Copyright (c) 2005-2011 by Appcelerator, Inc. All Rights Reserved.
* Licensed under the terms of the Eclipse Public License (EPL).
* Please see the license.txt included with this distribution for details.
* Any modifications to this file must keep this entire header intact.
*/
/*
* Created on Nov 12, 2004
*
* @author Fabio Zadrozny
*/
package org.python.pydev.editor.codecompletion.revisited.modules;
import org.python.pydev.core.IToken;
import org.python.pydev.editor.codecompletion.revisited.AbstractToken;
import org.python.pydev.editor.codecompletion.revisited.visitors.AbstractVisitor;
import org.python.pydev.editor.codecompletion.revisited.visitors.Definition;
import org.python.pydev.parser.jython.SimpleNode;
import org.python.pydev.parser.jython.ast.Attribute;
import org.python.pydev.parser.jython.ast.ClassDef;
import org.python.pydev.parser.jython.ast.FunctionDef;
import org.python.pydev.parser.jython.ast.Import;
import org.python.pydev.parser.jython.ast.ImportFrom;
import org.python.pydev.parser.jython.ast.Name;
import org.python.pydev.parser.jython.ast.NameTok;
import org.python.pydev.parser.jython.ast.keywordType;
import org.python.pydev.parser.visitors.NodeUtils;
/**
* @author Fabio Zadrozny
*/
public class SourceToken extends AbstractToken {
private static final long serialVersionUID = 1L;
/**
* The AST that generated this SourceToken
*/
private SimpleNode ast;
/**
* If this token ended up being an alias to a function def, this is the original def.
*/
private FunctionDef aliased;
/**
* @param node
*/
public SourceToken(SimpleNode node, String rep, String args, String doc, String parentPackage) {
super(rep, doc, args, parentPackage, getType(node));
this.ast = node;
}
/**
* @param node
*/
public SourceToken(SimpleNode node, String rep, String args, String doc, String parentPackage, int type) {
super(rep, doc, args, parentPackage, type);
this.ast = node;
}
/**
* @param node
*/
public SourceToken(SimpleNode node, String rep, String doc, String args, String parentPackage, String originalRep,
boolean originalHasRep) {
super(rep, doc, args, parentPackage, getType(node), originalRep, originalHasRep);
this.ast = node;
}
/**
*
* @return the completion type depending on the syntax tree.
*/
public static int getType(SimpleNode ast) {
if (ast instanceof ClassDef) {
return IToken.TYPE_CLASS;
} else if (ast instanceof FunctionDef) {
return IToken.TYPE_FUNCTION;
} else if (ast instanceof Name) {
return IToken.TYPE_ATTR;
} else if (ast instanceof Import || ast instanceof ImportFrom) {
return IToken.TYPE_IMPORT;
} else if (ast instanceof keywordType) {
return IToken.TYPE_ATTR;
} else if (ast instanceof Attribute) {
return IToken.TYPE_ATTR;
}
return IToken.TYPE_UNKNOWN;
}
public void setAst(SimpleNode ast) {
this.ast = ast;
}
public SimpleNode getAst() {
return ast;
}
/**
* @return line starting at 1
*/
public int getLineDefinition() {
return NodeUtils.getLineDefinition(getRepresentationNode());
}
private SimpleNode getRepresentationNode() {
if (ast instanceof Attribute) {
Attribute attr = (Attribute) ast;
while (attr != null) {
String r = NodeUtils.getRepresentationString(attr);
if (r != null && r.equals(rep)) {
return attr;
}
if (attr.value instanceof Attribute) {
attr = (Attribute) attr.value;
} else {
r = NodeUtils.getRepresentationString(attr.value);
if (r != null && r.equals(rep)) {
return attr.value;
}
break;
}
}
}
return ast;
}
/**
* @return col starting at 1
*/
public int getColDefinition() {
return NodeUtils.getColDefinition(ast);
}
int[] colLineEndToFirstDot;
int[] colLineEndComplete;
public int getLineEnd(boolean getOnlyToFirstDot) {
if (getOnlyToFirstDot) {
if (colLineEndToFirstDot == null) {
colLineEndToFirstDot = NodeUtils.getColLineEnd(getRepresentationNode(), getOnlyToFirstDot);
}
return colLineEndToFirstDot[0];
} else {
if (colLineEndComplete == null) {
colLineEndComplete = NodeUtils.getColLineEnd(getRepresentationNode(), getOnlyToFirstDot);
}
return colLineEndComplete[0];
}
}
public int getColEnd(boolean getOnlyToFirstDot) {
if (getOnlyToFirstDot) {
if (colLineEndToFirstDot == null) {
colLineEndToFirstDot = NodeUtils.getColLineEnd(getRepresentationNode(), getOnlyToFirstDot);
}
return colLineEndToFirstDot[1];
} else {
if (colLineEndComplete == null) {
colLineEndComplete = NodeUtils.getColLineEnd(getRepresentationNode(), getOnlyToFirstDot);
}
return colLineEndComplete[1];
}
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof SourceToken))
return false;
SourceToken s = (SourceToken) obj;
if (!s.getRepresentation().equals(getRepresentation()))
return false;
if (s.getLineDefinition() != getLineDefinition())
return false;
if (s.getColDefinition() != getColDefinition())
return false;
return true;
}
@Override
public int hashCode() {
return 7 * getLineDefinition() * getColDefinition();
}
public boolean isImport() {
if (ast instanceof Import || ast instanceof ImportFrom) {
return true;
}
return false;
}
public boolean isImportFrom() {
return ast instanceof ImportFrom;
}
public boolean isWildImport() {
return ast instanceof ImportFrom && AbstractVisitor.isWildImport((ImportFrom) ast);
}
public boolean isString() {
return AbstractVisitor.isString(ast);
}
/**
* This representation may not be accurate depending on which tokens we are dealing with.
*/
public int[] getLineColEnd() {
if (ast instanceof NameTok || ast instanceof Name) {
//those are the ones that we can be certain of...
return new int[] { getLineDefinition(), getColDefinition() + getRepresentation().length() };
}
throw new RuntimeException("Unable to get the lenght of the token:" + ast.getClass().getName());
}
/**
* Updates the parameter, type and docstring based on another token (used for aliases).
*/
public void updateAliasToken(SourceToken methodTok) {
this.args = methodTok.getArgs();
this.type = methodTok.getType();
this.doc = methodTok.getDocStr();
SimpleNode localAst = methodTok.getAst();
if (localAst instanceof FunctionDef) {
this.aliased = (FunctionDef) localAst;
} else {
this.aliased = methodTok.getAliased();
}
}
/**
* @return the function def to which this token is an alias to (or null if it's not an alias).
*/
public FunctionDef getAliased() {
return aliased;
}
private Definition definition;
public void setDefinition(Definition d) {
this.definition = d;
}
public Definition getDefinition() {
return this.definition;
}
}